import React, { useState } from 'react';
import PropTypes from 'prop-types';
import cn from 'classnames';
import get from 'lodash/get';
import {
	AddAlt20 as AddIcon,
	SubtractAlt20 as RemoveIcon,
} from '@carbon/icons-react';
import { useFormContext, useFieldArray, Controller } from 'react-hook-form';
import Button from '@kuiper-components/button';
import Input from '@kuiper-components/input';
import Switch from '@kuiper-components/switch';
import Notification from '@kuiper-components/notification';
import { name as pkgName } from '../../../../../../package.json';

import EmptyData from '../../../../components/empty/EmptyData';
import urlFortmat from '../../../../../common/urlFormat';
import isIP from '../../../../../common/isIP';
import { TASK_KEY_LABEL_MAP } from '../../../../../common/constants';
import confirm from '../../../../components/confirm';
import { Field } from '../../../../components/Form';
import Settings from './Settings';
import s from './TargetTable.module.css';

function TargetTable({
	className,
	name,
	taskType,
	taskCountLimit,
	taskCountBalance,
	planName,
	settingsButtonLabel,
	limit,
	CollectSettings: SettingsComponent,
}) {
	const {
		httpSettings: [httpDefaultSettings],
		pingSettings: [pingDefaultSettings],
	} = window.kuiper.app.config[pkgName]?.defaultJobSettings || {
		httpSettings: [],
		pingSettings: [],
	};
	const { control, setValue, getValues, watch } = useFormContext();
	const { fields, append, remove } = useFieldArray({
		control,
		name,
	});
	const [NotificationShow, setNotificationShow] = React.useState(false);
	const [batchDelete, setBatchDelete] = useState({});
	const values = watch(name) || [];
	const target = watch('target');
	const sourceIp = watch('sourceIp');
	const prevListLen = React.useMemo(() => fields.length, []);
	const feature = JSON.parse(sessionStorage.resD).feature;

	const refillTarget = () => {
		if (taskType === 'ping') {
			fields.forEach((x, i) => {
				setValue(`${taskType}Settings[${i}].target`, target.hostname);
			});
		} else {
			fields.forEach((x, i) => {
				let url;
				try {
					url = new URL(x.target);
				} catch {
					return;
				}
				url.host = target.host;
				url.protocol = target.protocol;
				setValue(`${taskType}Settings[${i}].target`, url.toString());
			});
		}
	};
	React.useMemo(refillTarget, [target]);
	if (
		taskType === 'http' &&
		(values[0]?.target || '').split('//')[0] !== target.protocol
	) {
		refillTarget();
	}

	const someEnabled = values.every(x => x.enable);
	const batchDeleteBtnDisabled = Object.values(batchDelete).every(v => !v);

	const rootUrl = urlFortmat({
		protocol: target?.protocol,
		host: target?.host,
	});

	const handleAllCheck = c => {
		const newBatchDelete = fields.reduce((obj, arr, idx) => {
			obj[idx] = c;
			return obj;
		}, {});
		setBatchDelete(newBatchDelete);
	};
	const handleRemove = (idx, e) => {
		e.preventDefault();
		confirm.warning({
			message: '您确定要删除此任务吗？删除后此操作不可撤销',
			okText: '删除',
			cancelText: '取消',
			onOk: () => {
				remove(idx);
			},
		});
	};

	const handleCheckChange = (val, index) => {
		setBatchDelete({ ...batchDelete, [index]: val });
	};

	const handleBatchDelete = () => {
		confirm.warning({
			message: `您确定要批量删除任务吗？删除后此操作不可撤销`,
			okText: '删除',
			cancelText: '取消',
			onOk: () => {
				const ids = Object.entries(batchDelete).reduce((arr, [index, val]) => {
					if (val) {
						arr.push(parseInt(index));
					}
					return arr;
				}, []);
				remove(ids);
				setBatchDelete({});
			},
		});
	};
	const balanceNum = taskCountBalance + prevListLen - fields.length;
	const balance = balanceNum > 0 ? balanceNum : 0;
	const pingColumns = [
		{
			id: 'name',
			label: '任务名称*',
			className: s.col,
			width: 128,
			defaultValue: {},
			// eslint-disable-next-line
			renderer: ({ namePrefix, record }) => (
				<Field
					className={s.field}
					as={Input}
					name={`${namePrefix}.name`}
					defaultValue={get(record, 'name')}
					componentClassName={s.nameInput}
					placeholder="请输入任务名称"
				/>
			),
		},
		{
			id: 'target',
			label: '域名*',
			className: s.col,
			width: 480,
			defaultValue: { target: target?.host },
			// eslint-disable-next-line
			renderer: ({ namePrefix, record }) => (
				<Field
					className={s.field}
					componentClassName={s.input}
					as={Input}
					name={`${namePrefix}.target`}
					defaultValue={get(record, 'target')}
					disabled
				/>
			),
		},
		{
			id: 'settings',
			label: '参数配置',
			className: s.col,
			width: 128,
			defaultValue: {
				interval: pingDefaultSettings.interval,
				collect: pingDefaultSettings.collect,
				alert: pingDefaultSettings.alert,
			},
			// eslint-disable-next-line
			renderer: ({ namePrefix, record, index }) => {
				return (
					<Settings
						name={namePrefix}
						defaultValue={record}
						buttonLabel={settingsButtonLabel}
						taskType={taskType}
					>
						<SettingsComponent
							name={namePrefix}
							limit={limit}
							defaultValue={record}
						/>
					</Settings>
				);
			},
		},
		{
			id: 'enable',
			label: '监测开关',
			field: 'enable',
			className: s.col,
			width: 80,
			defaultValue: { enable: false },
			// eslint-disable-next-line
			renderer: ({ namePrefix, record }) => {
				return (
					<>
						<Controller
							name={`${namePrefix}.enable`}
							defaultValue={get(record, 'enable')}
							render={({ onChange, onBlur, value }) => {
								let value_ = value;
								if (!feature.pingTask) {
									value_ = false;
								}
								return (
									<Switch
										onChange={checked => {
											if (!feature.pingTask) {
												onChange(false);
												if (NotificationShow) return;
												setNotificationShow(true);
												Notification.error({
													message: '未开通此配置',
													placement: 'top',
													style: { width: '25rem' },
													onClose: () => {
														setNotificationShow(false);
													},
												});
											} else {
												onChange(checked);
											}
										}}
										onBlur={onBlur}
										checked={value_}
									/>
								);
							}}
						/>
					</>
				);
			},
		},
		// {
		// 	id: 'actions',
		// 	label: '',
		// 	className: s.col,
		// 	width: '2rem',
		// 	defaultValue: {},
		// 	// eslint-disable-next-line
		// 	renderer: ({ index }) => (
		// 		<Button
		// 			className={s.btn}
		// 			link
		// 			primary
		// 			onClick={e => handleRemove(index, e)}
		// 		>
		// 			<RemoveIcon className={s.removeIcon} />
		// 		</Button>
		// 	),
		// },
	];

	const httpColumns = [
		{
			id: 'check',
			label: 'check',
			className: s.col,
			width: 16,
			defaultValue: {},
			// eslint-disable-next-line
			renderer: ({ namePrefix, record, index }) => {
				return (
					<Input
						type="checkbox"
						checked={batchDelete[index]}
						onChange={val => handleCheckChange(val, index)}
					/>
				);
			},
		},
		{
			id: 'name',
			label: '任务名称*',
			className: s.col,
			width: 128,
			defaultValue: { name: '' },
			// eslint-disable-next-line
			renderer: ({ namePrefix, record }) => (
				<Field
					className={s.field}
					as={Input}
					name={`${namePrefix}.name`}
					defaultValue={get(record, 'name')}
					componentClassName={s.nameInput}
				/>
			),
		},
		{
			id: 'target',
			label: 'URL*',
			className: s.col,
			width: 480,
			defaultValue: { target: rootUrl },
			// eslint-disable-next-line
			renderer: ({ namePrefix, record }) => (
				<Field
					className={s.field}
					name={`${namePrefix}.target`}
					defaultValue={get(record, 'target')}
					render={({ onChange, value }) => {
						const handleHttpUrlChange = val => {
							onChange(
								urlFortmat({
									protocol: target?.protocol,
									host: target?.host,
									pathname: val,
								})
							);
						};
						const changeVul = () => {
							const url = value || rootUrl;
							const origin = new URL(url)?.origin;
							return url.replace(origin, '');
						};
						return (
							<Input
								className={cn(s.input, s.speInput)}
								before={
									<Input
										className={s.urlBefore}
										value={rootUrl}
										title={rootUrl}
										disabled={true}
									/>
								}
								onChange={val => handleHttpUrlChange(val)}
								// value={new URL(value || rootUrl)?.pathname}
								value={changeVul()}
							/>
						);
					}}
				/>
			),
		},
		{
			id: 'settings',
			label: '参数配置',
			className: s.col,
			width: 128,
			defaultValue: {
				interval: httpDefaultSettings.interval,
				collect: httpDefaultSettings.collect,
				alert: httpDefaultSettings.alert,
			},
			// eslint-disable-next-line
			renderer: ({ namePrefix, record }) => {
				return (
					<Settings
						name={namePrefix}
						defaultValue={record}
						buttonLabel={settingsButtonLabel}
						taskType={taskType}
					>
						<SettingsComponent
							name={namePrefix}
							limit={limit}
							defaultValue={record}
						/>
					</Settings>
				);
			},
		},
		{
			id: 'enable',
			label: '监测开关',
			field: 'enable',
			className: s.col,
			width: 80,
			defaultValue: { enable: false },
			// eslint-disable-next-line
			renderer: ({ namePrefix, record }) => {
				return (
					<Controller
						name={`${namePrefix}.enable`}
						defaultValue={get(record, 'enable')}
						render={({ onChange, onBlur, value }) => {
							let value_ = value;
							if (!feature.httpTask) {
								value_ = false;
							}
							return (
								<Switch
									onChange={checked => {
										if (!feature.httpTask) {
											onChange(false);
											if (NotificationShow) return;
											setNotificationShow(true);
											Notification.error({
												message: '未开通此配置',
												placement: 'top',
												style: { width: '25rem' },
												onClose: () => {
													setNotificationShow(false);
												},
											});
											return;
										}
										if (checked && limit.httpMaxTaskEnable <= 0) {
											Notification.error({
												message: '当前套餐可启用HTTP任务监测数已达上限。',
												placement: 'top',
											});
										} else {
											onChange(checked);
										}
									}}
									onBlur={onBlur}
									checked={value_}
								/>
							);
						}}
					/>
				);
			},
		},
		{
			id: 'actions',
			label: '',
			className: s.col,
			width: 32,
			defaultValue: {},
			// eslint-disable-next-line
			renderer: ({ index }) => (
				<Button
					className={s.btn}
					link
					primary
					onClick={e => handleRemove(index, e)}
				>
					<RemoveIcon className={s.removeIcon} />
				</Button>
			),
		},
	];

	const handleToggleAll = checked => {
		if (checked && values.length > limit.httpMaxTask) {
			Notification.error({
				message: '当前套餐可启用HTTP任务监测数不足，不能开启所有HTTP任务监测',
				placement: 'top',
				style: { width: '20rem' },
			});
		}
		let enableNum =
			values.reduce((total, item) => {
				if (item.enable) {
					total.push(item);
				}
				return total;
			}, []).length || 1;

		setValue(
			name,
			values.map(val => {
				let enableValue = checked;
				if (checked) {
					if (enableNum > limit.httpMaxTask) {
						enableValue = val.enable;
					}
					enableNum++;
				}
				return {
					...val,
					enable: enableValue,
				};
			})
		);
	};

	const handleAdd = e => {
		e.preventDefault();
		if (balance <= 0) {
			Notification.error({
				message: 'HTTP任务数已达到上限，无法继续添加',
				placement: 'top',
				style: { width: '20rem' },
			});
			return;
		}
		const data = columns.reduce(
			(obj, x) => Object.assign(obj, x.defaultValue),
			{
				target: rootUrl,
			}
		);
		const ipNum = isIP(target.hostname);
		if (ipNum === 4) {
			data.collect.area_ipv6 = [];
		} else if (ipNum === 6) {
			data.collect.area = [];
		} else {
			const ipNum2 = isIP(sourceIp);
			if (ipNum2 === 4) {
				data.collect.area_ipv6 = [];
			} else if (ipNum2 === 6) {
				data.collect.area = [];
			} else {
				data.collect.area_ipv6 = [];
			}
		}
		append(data);
	};

	const handleCopyLastOne = e => {
		e.preventDefault();
		if (balance <= 0) {
			Notification.error({
				message: 'HTTP任务数已达到上限，无法继续添加',
				placement: 'top',
				style: { width: '22rem' },
			});
			return;
		}

		if (fields.length === 0) return;
		const values = getValues({ nest: true });
		const lastOne = values[name][fields.length - 1];

		append({
			...lastOne,
			_id: undefined,
			id: Date.now(),
		});
	};

	const columns = taskType === 'http' ? httpColumns : pingColumns;
	// React.useMemo(() => {
	// 	// 如果批量删除全部任务，则添加一条空的任务
	// 	if (fields.length > 0) return;
	// 	append(
	// 		columns.reduce((obj, x) => Object.assign(obj, x.defaultValue), {
	// 			target: rootUrl,
	// 			name: '',
	// 			id: Date.now(),
	// 		})
	// 	);
	// }, [fields]);

	const allCheck =
		values.length > 0 && values.every((c, idx) => batchDelete[idx]);

	return (
		<div className={cn(className, s.targetTable)}>
			<div className={s.title}>
				<div className={s.label}>监测地址</div>
				{taskType === 'http' && (
					<>
						<div className={s.planDescription}>
							您可以添加
							<mark>{feature.httpTask ? taskCountLimit : 0}个</mark>
							{TASK_KEY_LABEL_MAP[taskType]}
							任务，当前您还可添加
							<mark>{feature.httpTask ? balance : 0}个</mark>任务。
						</div>
						<div className={s.btnContainer}>
							<Button
								link
								disabled={batchDeleteBtnDisabled}
								onClick={handleBatchDelete}
								type="button"
								className={{ [s.btn]: !batchDeleteBtnDisabled }}
							>
								批量删除
							</Button>
						</div>
						<div className={s.toggle}>
							一键设置
							<Switch
								className={s.switch}
								checked={someEnabled}
								onClick={handleToggleAll}
								disabled={!feature.httpTask}
							/>
						</div>
					</>
				)}
			</div>
			<table className={s.table}>
				<thead className={s.header}>
					<tr>
						{columns.map(({ id, label, className, width }) => (
							<th
								key={id}
								className={cn(s.col, className)}
								style={{
									width: width || 'auto',
								}}
							>
								{label === 'check' ? (
									<Input
										type="checkbox"
										className={s.allCheck}
										onChange={handleAllCheck}
										key={id}
										checked={allCheck}
									/>
								) : (
									label
								)}
							</th>
						))}
					</tr>
				</thead>
				<tbody className={s.body}>
					{fields.map((record, index) => {
						const namePrefix = `${name}[${index}]`;
						return (
							// eslint-disable-next-line react/prop-types
							<tr key={`${record.id}${index}`} className={s.row}>
								{columns.map(({ id, className, width, renderer }) => {
									const text = renderer({
										index,
										record,
										namePrefix,
									});

									return (
										<td
											key={id}
											className={cn(s.col, className)}
											style={{ width: width }}
										>
											{text}
										</td>
									);
								})}
							</tr>
						);
					})}
				</tbody>
			</table>
			{values.length === 0 && <EmptyData />}
			<div className={s.actions}>
				{taskType === 'http' && (
					<>
						<Button link primary className={s.btn} onClick={handleAdd}>
							<AddIcon className={s.icon} />
							添加
						</Button>
						<Button
							link
							primary
							className={s.btn}
							disabled={values.length === 0}
							onClick={handleCopyLastOne}
						>
							复制上一条
						</Button>
					</>
				)}
			</div>
		</div>
	);
}

TargetTable.propTypes = {
	className: PropTypes.string,
	name: PropTypes.string.isRequired,
	taskType: PropTypes.oneOf(['http', 'ping']).isRequired,
	settingsButtonLabel: PropTypes.string,
	CollectSettings: PropTypes.elementType,
	planName: PropTypes.string,
	taskCountLimit: PropTypes.number.isRequired,
	taskCountBalance: PropTypes.number.isRequired,
	limit: PropTypes.shape({
		httpMaxFreq: PropTypes.shape({
			unit: PropTypes.string,
			value: PropTypes.number,
		}),
		httpMaxTask: PropTypes.number,
		httpMaxTaskEnable: PropTypes.number,
		aviliableMaxNode: PropTypes.number,
	}).isRequired,
	formSubmit: PropTypes.func,
};
TargetTable.defaultProps = {
	className: s.targetTable,
	settingsButtonLabel: '配置',
	taskCountLimit: 0,
	taskCountBalance: 0,
};

export default TargetTable;
